
using System;
using UnityEditor;
using UnityEngine;
using System.Collections.Generic;
using UnityEngine.Rendering;
using  XYRendering.Runtime;




namespace XYTerrain.Editor
{
    public class TerrainAlphaMapSetter : EditorWindow
    {

        private readonly string[] mapResolutionName =
        {
                "64", "128", "256", "512", "1024", "2048"
            };

        private readonly int[] mapResolution =
        {
                64, 128, 256, 512, 1024, 2048
            };

        private readonly int[] heightMapResolution =
        {
                65, 129, 257, 513, 1025, 2049
            };

        private readonly string[] heightMapResolutionName =
        {
                "65", "129" ,"257", "513","1025","2049"
        };
        

        
        

        





        public static string windowsName = "地形批量设置修改";
        public List<Terrain> allTerrain = new List<Terrain>();

        private SerializedObject _serObj;
        private SerializedProperty _terrainpty;
        private UnityEngine.Rendering.ShadowCastingMode _shadowCastingMode;


        public VolumeParameter<ReflectionProbeUsage> reflectionProbUsage = new ObjectParameter<ReflectionProbeUsage>(ReflectionProbeUsage.Off){overrideState = false};
        public SerializedProperty _reflectionProbUsage_pty;

        public OverriderBool boolValue  = new OverriderBool(true);
        public OverriderShadowCast shadowCast = new OverriderShadowCast(ShadowCastingMode.Off);
        public OverProbeSetting probeSetting = new OverProbeSetting(ReflectionProbeUsage.Off);
        
        
        private int terrainSize;
        private string levelName;
        
        
        [MenuItem("Tools/Nature Manufacture/XY/地形批量设置修改")]
        public static void OpenWindow()
        {
            var window = EditorWindow.GetWindow<TerrainAlphaMapSetter>(windowsName);
            TerrainData tdata;
            Terrain t;
        }
        
        
        
        public void OnEnable()
        {
            _serObj = new SerializedObject(this);
            _terrainpty = _serObj.FindProperty("allTerrain");
            _reflectionProbUsage_pty = _serObj.FindProperty("reflectionProbUsage");
        }


        int mapResolutionSelection = 0;


        public readonly GUIContent mapContex = new GUIContent("ControlTextureResolution", "控制贴图分辨率");

        
        
            

        private void OnGUI()
        {
        
            EditorGUILayout.Space(5);
            DrawControllerMapGUI();
            EditorGUILayout.Space(10);
            DrawSetting();
            EditorGUILayout.Space(10);
            DrawRename();
        }

     
       
        
        public void DrawSetting()
        {

            EditorGUILayout.BeginVertical(EditorStyles.helpBox); 
            EditorGUILayout.LabelField("覆盖参数内容");
            EditorGUILayout.HelpBox("不需要修改的参数将名称前的勾子去掉",MessageType.Info);
            
            
            shadowCast.DrawEditorIns("ShadowCast");
            probeSetting.DrawEditorIns("ReflectionProbe");


            if (GUILayout.Button("覆盖地形参数"))
            {
                OverriderTerrainSetting();
            }
            
            EditorGUILayout.EndVertical(); 
            
        }

        

        void DrawParameter<T>(VolumeParameter<T> v)
        {
            EditorGUILayout.Toggle(v.overrideState);
        }


        private void OverriderAllTerrainSetting()
        {
            
           EditorGUILayout.LabelField("阴影模式");
           EditorGUILayout.BeginVertical(EditorStyles.helpBox);
           EditorGUILayout.Space(10);
           _shadowCastingMode = (UnityEngine.Rendering.ShadowCastingMode) EditorGUILayout.EnumPopup("ShadowCast",_shadowCastingMode)  ;
           EditorGUILayout.Space(10);
           if (GUILayout.Button("保存"))
           {
               OverriderTerrainSetting();
                EditorUtility.DisplayDialog("提示", "修改完成", "ok");
           }
           EditorGUILayout.BeginVertical(EditorStyles.helpBox);
           
           
        }


        private void OverriderTerrainSetting()
        {
            foreach (var i in allTerrain)
            {

                if (shadowCast.overrider) i.shadowCastingMode = shadowCast.value;
                if (probeSetting.overrider) i.reflectionProbeUsage = probeSetting.value;
                
                EditorUtility.SetDirty(i);
            } 
        }
        
        
       #region   绘制方法 

        private void DrawTerrainList()
        {
            
            EditorGUILayout.BeginVertical(EditorStyles.helpBox);
            
            if (_terrainpty != null) EditorGUILayout.PropertyField(_terrainpty);

            _serObj.Update();
            EditorGUI.BeginChangeCheck();
            if (EditorGUI.EndChangeCheck())
            {
                _serObj.ApplyModifiedProperties();
            }


            EditorGUILayout.BeginHorizontal();
            if(GUILayout.Button("获取所有地形组件")){

                var terrains = FindObjectsOfType<Terrain>();

                if(allTerrain==null)allTerrain=new List<Terrain>();
                allTerrain.Clear();
                foreach(var i in terrains){
                    allTerrain.Add(i);
                }
                
            }

            if(GUILayout.Button("移除列表所有内容")){
                if (allTerrain == null) return;
                allTerrain.Clear();
            }

            EditorGUILayout.EndHorizontal();

            EditorGUILayout.EndVertical();

        }


        public void DrawControllerMapGUI()
        {


            
            
            EditorGUILayout.BeginVertical(EditorStyles.helpBox);
            EditorGUILayout.LabelField("地形控制贴图尺寸批量修改");
            DrawTerrainList();
            EditorGUILayout.BeginVertical(EditorStyles.helpBox);

            mapResolutionSelection = EditorGUILayout.Popup(mapContex, mapResolutionSelection, mapResolutionName);

            if (GUILayout.Button("开始处理"))
            {

                SetAllTerrainTex();

            }


            EditorGUILayout.EndVertical();
            EditorGUILayout.EndVertical();


        }



        private void DrawRename()
        {
            EditorGUILayout.BeginVertical(EditorStyles.helpBox);
            EditorGUILayout.LabelField("地块重命名");
            levelName = EditorGUILayout.TextField("关卡名称", levelName);
            terrainSize = EditorGUILayout.IntField("单个Terrain尺寸", terrainSize);
            if (GUILayout.Button("重新命名"))
            {
                RenameTerrain();
            }
            
            
            EditorGUILayout.EndVertical();

        }
        
       #endregion 
        
        
        public int size = 512;
        public float GetColorIndex(Color col, int index)
        {
            if (index == 0) return col.r;
            else if (index == 1) return col.g;
            else if (index == 2) return col.b;
            else if (index == 3) return col.a;
            Debug.LogError("Index超出4");
            return 0;
        }




        



        [ContextMenu("ChangeAllTex")]
        public void SetAllTerrainTex()
        {
            if(allTerrain==null)return;
            for (int i = 0; i < allTerrain.Count; i++)
            {
                EditorUtility.DisplayProgressBar("", $"正在处理第{i}份地形数据.\n 共{allTerrain.Count}份 ", (i + 1) / (float)allTerrain.Count);
                SetSingleControlMapData(allTerrain[i]);
            }

            EditorUtility.ClearProgressBar();

        }

        public void SetSingleControlMapData(Terrain terrain)
        {
            // var terrains =  FindObjectsOfType<Terrain>();
            size = mapResolution[mapResolutionSelection];

            var terrainData = terrain.terrainData;

            var alphaData = terrainData.GetAlphamaps(0, 0, terrainData.alphamapWidth, terrainData.alphamapHeight);

            var layerNum = terrainData.alphamapLayers;


            var NewAlphaData = new float[size, size, layerNum];
            // TODO 通过Texture2D插值？

            Texture2D[] originTex = terrainData.alphamapTextures;
            Texture2D[] newTex = new Texture2D[layerNum];

            RenderTexture tempRt = RenderTexture.GetTemporary(size, size, 0);



            for (int ln = 0; ln < originTex.Length; ln++)
            {

                newTex[ln] = new Texture2D(size, size, originTex[ln].format, true);

                Graphics.Blit(originTex[ln], tempRt);
                RenderTexture.active = tempRt;
                newTex[ln].ReadPixels(new Rect(0, 0, size, size), 0, 0);
                newTex[ln].Apply();
                //-----------Debug 贴图--------------- 
                SavePreviewTex(newTex[ln], ln.ToString());
                //------------------------------------
            }
            RenderTexture.ReleaseTemporary(tempRt);


            float scale = alphaData.GetLength(0) / (float)(size);

            for (int width = 0; width < size; width++)
            {
                for (int height = 0; height < size; height++)
                {
                    int old_width = Mathf.FloorToInt(width * scale);

                    int old_height = Mathf.FloorToInt(height * scale);


                    for (int layer = 0; layer < layerNum; layer++)
                    {
                        int texId = Mathf.FloorToInt(layer / 4f);
                        float oldValue = GetColorIndex(newTex[texId].GetPixel(height, width), layer % 4);
                        NewAlphaData[width, height, layer] = oldValue;
                    }

                }
            }


            foreach (var i in newTex)
            {
                GameObject.DestroyImmediate(i);
            }

            Undo.RegisterCompleteObjectUndo(terrain, "TerrainData");
            terrainData.alphamapResolution = size;
            terrainData.SetAlphamaps(0, 0, NewAlphaData);
            EditorUtility.SetDirty(terrain);

        }


        private  Vector2Int GetBoundNum(Transform t)
        {
            var pos = t.transform.position;
            int x = Mathf.CeilToInt(pos.x / terrainSize);
            int z = Mathf.CeilToInt(pos.z / terrainSize);

            return new Vector2Int(x, z);
        }
        public void RenameTerrain()
        {
            foreach (var i in allTerrain)
            {
                var vec =  GetBoundNum(i.transform);
                i.name = $"{levelName}_Terrain_X{vec.x}_Z{vec.y}";
                i.terrainData.name = $"{levelName}_TerrainData_X{vec.x}_Z{vec.y}";
                EditorUtility.SetDirty(i);
                EditorUtility.SetDirty(i.terrainData);
            } 
        }
        




        // TODO 封装上面的赋值操作，应用到heightMap的设置上。
        private void SetAllTerrainHegihtMap()
        {

        }


        bool texDebug;
        private void SavePreviewTex(Texture2D tex, string id)
        {

            if (!texDebug) return;
            var bytes = tex.EncodeToPNG();
            string path = Application.dataPath + "/Preview" + id + ".png";
            var file = System.IO.File.Open(path, System.IO.FileMode.OpenOrCreate);
            file.Write(bytes, 0, bytes.Length);
            file.Close();
            AssetDatabase.SaveAssets();
            AssetDatabase.Refresh();
            Debug.Log("预览图生成完毕 位置 ：" + path);
        }
        
    }


    
}

